/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mygameframework.isoengine;

import java.awt.Point;
import java.awt.Rectangle;

/**
 *
 * @author bill
 */
public class Scroller {
    /** screenspace是相对于窗体左上角为原点的一个矩形空间,
     * 当使用JFrame或Frame作渲染组件,screenSpace的x和y坐标 
     * 根据窗体的边框宽(dx偏移值)和标题栏高(dy偏移值)决定, 公式为x=0+dx ,y=0+dy
     * .当使用JPanel或Canvas作渲染组件时,dx,dy 为0,因为左上角原点是JPanel或Canvas
     * 的左上角,而非窗体JFrame或Frame的左上角,因而不计标题栏和边框的值在内.
     *  
     */
    private Rectangle screenSpace;
    /**
     * 当地图是diamond,worldSpace的x为负,y始终为0
     * 其它类形地图x和y始终为0
     * 见 calculateWorldSpace
     */
    private Rectangle worldSpace;
    /** anchorspace一般是worldspace内的一个矩形空间,根据水平和垂直的滚动模式不同,
     * anchorspace也不同;
     * 当地图滚动模式是圆球形(WRAP_MODE_WRAP),anchorSpace=worldSpace;
     * 若地图滚动模式是圆球形(WRAP_MODE_WRAP)且screenSpace大于worldSpace,anchorSpace宽高为0,并居中于
     * screenSpace;(anchorSpace宽高为0说明ptScreenAnchor没活动空间,屏幕不能移动)
     * 见 calculateAnchorSpace 方法
     */
    private Rectangle anchorSpace;
    /**如果地图滚动模式是WRAP_MODE_CLIP,该点被限制于anchorSpace内
     * 
     */
    private Point ptScreenAnchor;
    /*存了一个tileSet的dstRect*/
    private Rectangle dstRect;
    
    private SCROLLER_WRAP_MODE enumHorizontal;
    private SCROLLER_WRAP_MODE enumVertical;
    
    private TilePlotter plotter;
    private int mw,  mh;

    public Scroller() {
        this.screenSpace=new Rectangle();
        this.worldSpace=new Rectangle();
        this.anchorSpace=new Rectangle();
        this.ptScreenAnchor=new Point();
        this.enumHorizontal=SCROLLER_WRAP_MODE.WRAP_MODE_NONE;
        this.enumVertical=SCROLLER_WRAP_MODE.WRAP_MODE_NONE;
    }

    public Scroller(TilePlotter tp,Rectangle screenSpace,int mapw,int maph,
            SCROLLER_WRAP_MODE enumHorizontal, SCROLLER_WRAP_MODE enumVertical
            ,Rectangle dstRect) {
        this.plotter=tp;
        this.mw=mapw;this.mh=maph;
        this.screenSpace=screenSpace;
        this.dstRect=dstRect;
        this.enumHorizontal = enumHorizontal;
        this.enumVertical = enumVertical;
        this.calculateWorldSpace(plotter,dstRect, mw, mh);
        this.calculateAnchorSpace();
    }
    public void calculateWorldSpace(){
        this.calculateWorldSpace(this.plotter,dstRect, mw, mh);
    }
    public void calculateWorldSpace(TilePlotter p,Rectangle dstRect,int mapw,int maph){
        System.out.println("[Scroller.calWorldSpace] dstRect : "+dstRect);
        worldSpace.setBounds(0, 0, 0, 0);
        Rectangle src2=new Rectangle(worldSpace);
        Rectangle tmp=new Rectangle(dstRect);
        Point tpPlot;
        Point ptMap=new Point();
        int minX =0,minY=0,maxX=0,maxY=0;
        for(ptMap.y=0;ptMap.y<maph;ptMap.y++){
            for(ptMap.x=0;ptMap.x<mapw;ptMap.x++){
                tpPlot=p.plotTile(ptMap);
//                tmp.add(tpPlot);
                tmp.translate(tpPlot.x, tpPlot.y);
                
                if(tmp.x<minX) minX=tmp.x;
                if(tmp.y<minY) minY=tmp.y;
                
                if(tmp.getMaxX()>maxX) maxX=(int) tmp.getMaxX();
                if(tmp.getMaxY()>maxY) maxY=(int) tmp.getMaxY();
                
//                Rectangle.union(tmp , worldSpace, worldSpace);
                tmp.translate(-tpPlot.x, -tpPlot.y);
                
            }
        }
        worldSpace.setFrameFromDiagonal(minX, minY, maxX, maxY);
//        tmp.width+=p.getTileWidth();
//        tmp.height+=p.getTileHeight();
//        this.worldSpace=tmp;
        System.out.println("min "+minX+" "+minY+"  max:"+maxX+" "+maxY);
        System.out.println("[Scroller.calcuWorldSpace]worldSpace :"+worldSpace);
    }
    /***
     * 调用前确保ScreeSpace以设定
     */
    public void calculateAnchorSpace(){
        anchorSpace=new Rectangle(worldSpace);
        if (worldSpace.width > screenSpace.width) {
            //不是'圆球地图'就减 屏幕宽高
            if( getHorizontalMode()!=SCROLLER_WRAP_MODE.WRAP_MODE_WRAP){
                anchorSpace.width -= screenSpace.width;
            }
        } else {//当地图小于屏幕时,居中
            anchorSpace.width = 0;//0
            if(plotter.getMapType()!=MapType.MAP_DIAMOND)
                anchorSpace.x=-(screenSpace.width/2-worldSpace.width/2);
            else
                anchorSpace.x=-(screenSpace.width/2-plotter.getTileWidth()/2);
        }
        if (worldSpace.height > screenSpace.height) {
            if(getVerticalMode()!=SCROLLER_WRAP_MODE.WRAP_MODE_WRAP){
                anchorSpace.height -= screenSpace.height;
            }
        } else {//当地图小于屏幕时,居中
            anchorSpace.height = 0;//0
            anchorSpace.y=-(screenSpace.height/2-worldSpace.height/2);
        }
        
    }
    public boolean isWorldCoord(Point point){
        return worldSpace.contains(point);
    }
    public boolean isAnchorCoord(Point point){
        return anchorSpace.contains(point);
    }
    public boolean isScreenCoord(Point point){
        return screenSpace.contains(point);
    }
    public void translateAnchorSpace(int dx,int dy){
        anchorSpace.translate(dx, dy);
    }
    public void translateWorldSpace(int dx,int dy){
        worldSpace.translate(dx, dy);
    }
    public void translateScreenSpace(int dx,int dy){
        screenSpace.translate(dx, dy);
    }
    public void moveScreenAnchor(int dx,int dy,boolean wheatherWarpAnchor){
        if(dx==0 && dy==0)return;
        ptScreenAnchor.x+=dx;
        ptScreenAnchor.y+=dy;
//        System.out.println("pt s a "+ptScreenAnchor);
        if(wheatherWarpAnchor)
            warpAnchor();
    }
    /***
     * 
     * 会减去 screenSpace的x y 作为修正修偏
     * @param screen
     * @return a point for world space
     */
    public Point screenToWorld(Point screen){
//        Point result=(Point) screen.clone();
        Point result=new Point(screen);
        result.x-=screenSpace.x;//偏移,如titlebar ,边框 所导致的偏移值
        result.y-=screenSpace.y;
        result.x+=ptScreenAnchor.x;
        result.y+=ptScreenAnchor.y;
        return result;
    }
    /**
     * 会加上 screenSpace的x y 作为修正修偏
     * @param world
     * @return 
     */
    public Point worldToScreen(Point world){
//        Point result=(Point) world.clone();
        Point result=new Point(world);
//        result.x+=screenSpace.x;//偏移,如titlebar ,边框 所导致的偏移值
//        result.y+=screenSpace.y;
        result.x-=ptScreenAnchor.x;
        result.y-=ptScreenAnchor.y;
        result.x+=screenSpace.x;//偏移,如titlebar ,边框 所导致的偏移值
        result.y+=screenSpace.y;
        return result;
    }
    /***
     * 对Screen Anchor进行检测,确保其在anchor space内
     */
    public void warpAnchor(){
        switch (enumHorizontal) {
            case WRAP_MODE_CLIP:
                if (ptScreenAnchor.x < anchorSpace.x) {
//                     System.out.println(" clip x<" );
                    ptScreenAnchor.x = anchorSpace.x;
                }
                if(ptScreenAnchor.x>anchorSpace.getMaxX()){
//                System.out.println(" clip x>=" );
                    ptScreenAnchor.x=(int) (anchorSpace.getMaxX());
                }
                break;
            case WRAP_MODE_WRAP:
                if(anchorSpace.getWidth()==0) {//worldspace小于screenSpace
                    ptScreenAnchor.x=anchorSpace.x;
                    break;
                }
                while(ptScreenAnchor.x<anchorSpace.x){
                    System.out.println("wrap x<" );
                    //anchorSpace.getWidth()==screenSpace.getWidth()
                    ptScreenAnchor.x+=anchorSpace.getWidth();
                }
                while(ptScreenAnchor.x>=anchorSpace.getMaxX()){
                    System.out.println("wrap x>=" +anchorSpace);
                    ptScreenAnchor.x-=anchorSpace.getWidth();
                }
                break;
            default://WRAP_MODE_NONE
                //do nothing;
        }
        switch (enumVertical) {
            case WRAP_MODE_CLIP:
                if(ptScreenAnchor.y<anchorSpace.y){
//                    System.out.println("c y<");
                    ptScreenAnchor.y=anchorSpace.y;
                }
                if(ptScreenAnchor.y>anchorSpace.getMaxY()){
//                    System.out.println("c y>");
                    ptScreenAnchor.y=(int) (anchorSpace.getMaxY());
                    
                }
                break;
            case WRAP_MODE_WRAP:
            if(anchorSpace.getHeight()==0){//worldspace小于screenSpace
                ptScreenAnchor.y=anchorSpace.y;
                break;
            }
                while(ptScreenAnchor.y<anchorSpace.y){
                    System.out.println("wrap y<");
                    ptScreenAnchor.y+=anchorSpace.getHeight();
                }
                while(ptScreenAnchor.y>=anchorSpace.getMaxY()){
                    System.out.println("wrap y>=");
                    ptScreenAnchor.y-=anchorSpace.getHeight();
                }
                break;
            default://WRAP_MODE_NONE
                //do nothing;
        }
    }
    
    
    public Rectangle getAnchorSpace() {
        return anchorSpace;
    }

    public void setAnchorSpace(Rectangle anchorSpace) {
        this.anchorSpace = anchorSpace;
    }

    public SCROLLER_WRAP_MODE getHorizontalMode() {
        return enumHorizontal;
    }

    public void setHorizontalMode(SCROLLER_WRAP_MODE enumHorizontal) {
        this.enumHorizontal = enumHorizontal;
    }

    public SCROLLER_WRAP_MODE getVerticalMode() {
        return enumVertical;
    }

    public void setVerticalMode(SCROLLER_WRAP_MODE enumVertical) {
        this.enumVertical = enumVertical;
    }

    public Point getScreenAnchor() {
        return ptScreenAnchor;
    }

    public void setScreenAnchor(Point ptScreenAnchor) {
        this.ptScreenAnchor = ptScreenAnchor;
    }

    public Rectangle getScreeSpace() {
        return screenSpace;
    }

    public void setScreeSpace(Rectangle screeSpace) {
        this.screenSpace = new Rectangle(screeSpace);
    }

    public Rectangle getWorldSpace() {
        return worldSpace;
    }

    public void setWorldSpace(Rectangle worldSpace) {
        this.worldSpace = worldSpace;
    }

    public TilePlotter getPlotter() {
        return plotter;
    }

    public void setPlotter(TilePlotter plotter) {
        this.plotter = plotter;
    }
    public void setMapSize(int w,int h){
        this.mw=w;
        this.mh=h;
    }

    public int getMapHeight() {
        return mh;
    }

    public int getMapWidth() {
        return mw;
    }
    
    /**
     * NONE 是什么也不做<br>
     * CLIP 是限制一定范围的屏幕滚动<br>
     * WRAP 是'地球式' 从一边边限能走到另一边
     */
    public enum SCROLLER_WRAP_MODE{
        WRAP_MODE_NONE,WRAP_MODE_CLIP,WRAP_MODE_WRAP;
    }
}
